home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993 April: Penguin on DISC / ADC Developer CD (1993-04) (''Penguin On DISC'')_iso / Dev.CD Apr 93.iso / System Software / System Extensions / AppleScript Beta / Development Tools / Sample Applications / 7Edit 3.0d7 / 7Edit Source / 7Edit Pascal 3.0d7 / SVEditWindow.p < prev   
Encoding:
Text File  |  1992-11-24  |  31.2 KB  |  1,096 lines  |  [TEXT/MPS ]

  1. {[d-,h-,k+,o=100,q+,r+,rec+,t=2,u+,:+,j=15/20/25/30/35/40/45/50/57/1$]} {Pasmat opts!}
  2.  
  3. {$S Window}
  4.  
  5. UNIT SVEditWindow;
  6. (*
  7.     SVEditWindow.p
  8.     
  9.     Version 3.0d7
  10.     
  11.     Copyright © Apple Computer UK Ltd. 1991,1992
  12.     
  13.     All rights reserved.
  14.     
  15.     Produced by : UK Developer Technical Support
  16.     AppleLink   : UK.DTS
  17. *)
  18.  
  19.   {The window and text handling routines for the SVEdit example program}
  20.  
  21.     {
  22.         New for 3.0d2
  23.         
  24.         19-Feb-92 : NH    : Implement PrintWindow
  25.                       Change PageStarts to PageEnds
  26.                       Fix out by one in GetPageEnds
  27.                                             
  28.         26-Feb-92    : NH    : Put in final printing implementation
  29.                                         : Fix inThumb scrolling
  30.                                         : Put in kTextOffset to replace kTextMargin for better borders
  31.                                         
  32.         28-Feb-92 : NH  : gCurrSection zapped - Incoming AppleEvents make keeping track
  33.                           via a global very messy. Now check to see when in a section as
  34.                                             required.
  35.                                             
  36.         New for 3.0d3
  37.         
  38.         07-Apr-92 : NH  : PrPicFile added to PrintWindow.
  39.         
  40.          3-Jun-92 : NH  : Fixed bug in DrawPageBreaks (kTextOffset added twice)
  41.                                              Put in progress dialog for printing.
  42.                                             
  43.          7-Jun-92 : NH  : Fixed bug in PrintWindow - pageBounds was a pointer,
  44.                           never initialised so randomly trashed memory when calced
  45.                                             pageBounds for printing
  46.                                             
  47.                                             oldMax,oldValue,theResult - dead vars - removed
  48.         New for 3.0d5
  49.         
  50.         21-Aug-92 : NH :  Added isForNewDoc to NewDocument.
  51.                           Also count of new windows for Untitled #
  52.                                             Eversaved implemented instead of name = untitled
  53.     }
  54.     
  55.   INTERFACE
  56.  
  57.     USES MemTypes, QuickDraw, OSIntf, ToolIntf, Traps, Editions, Printing, SVEditGlobals, SVEditUtils,
  58.  
  59.          SVEditions, SVAppleEvents;
  60.  
  61.     FUNCTION DPtrFromWindowPtr(w: WindowPtr): DPtr;
  62.  
  63.     PROCEDURE MyGrowWindow(w: WindowPtr;
  64.                            p: Point);
  65.  
  66.     PROCEDURE DoZoom(w: WindowPtr;
  67.                      c: INTEGER;
  68.                      p: Point);
  69.  
  70.     PROCEDURE DoContent(theWindow: WindowPtr;
  71.                         theEvent: EventRecord);
  72.  
  73.         PROCEDURE DoActivate(theWindow: WindowPtr;
  74.                                                  activate : BOOLEAN);
  75.  
  76.     PROCEDURE DoUpdate(theDoc: DPtr);
  77.  
  78.     FUNCTION  NewDocument(isForOldDoc:Boolean): DPtr;
  79.  
  80.     PROCEDURE CloseMyWindow(aWindow: WindowPtr);
  81.  
  82.     PROCEDURE ShowSelect(theDoc: DPtr);
  83.  
  84.     PROCEDURE AdjustScrollbars(theDoc: DPtr;
  85.                                needsResize: BOOLEAN);
  86.                                                              
  87.     PROCEDURE GetWinContentRect(theWindow:WindowPtr; VAR r:Rect);
  88.         
  89.     PROCEDURE ResizeWindow(theDoc: DPtr);
  90.  
  91.     PROCEDURE ResizePageSetupForDocument(theDoc: DPtr);
  92.         
  93.         PROCEDURE InvalidateDocument(theDoc: DPtr);
  94.         
  95.         PROCEDURE DrawPageExtras(theDoc:DPtr);
  96.         
  97.         PROCEDURE PrintWindow(theDoc:DPtr; askUser:BOOLEAN);
  98.  
  99.   IMPLEMENTATION
  100.         
  101.         USES Packages;
  102.         
  103.     CONST
  104.       kControlInvisible = 0;
  105.       kControlVisible     = $FF;
  106.       kScrollbarWidth     = 16;
  107.       kScrollbarAdjust     = kScrollbarWidth - 1;
  108.       kScrollTweek           = 2;
  109.             kTextOffset                = 5; 
  110.       kButtonScroll          = 10;
  111.             
  112.             kMaxPages           = 1000; (* Assumes pages > 32 pixels high *)
  113.             
  114.             kHOffset                     = 20; (* Stagger window offsets *)
  115.             kVOffset                     = 20;
  116.             
  117.             kTBarHeight             = 20;
  118.             kMBarHeight             = 20;
  119.             
  120.         TYPE  
  121.             PageEndsArray     = ARRAY [1..kMaxPages] OF INTEGER;
  122.             PPageEnds         = ^PageEndsArray;
  123.             HPageEnds         = ^PPageEnds;
  124.  
  125.       {$S Window}
  126.  
  127.     FUNCTION DPtrFromWindowPtr(w: WindowPtr): DPtr;
  128.  
  129.       BEGIN
  130.         IF w = NIL THEN
  131.           DPtrFromWindowPtr := NIL
  132.         ELSE
  133.           DPtrFromWindowPtr := DPtr(GetWRefCon(w));
  134.       END;
  135.  
  136.     {$S main}
  137.                     
  138.    PROCEDURE AdjustTE(theDoc: DPtr);
  139.  
  140. { Scroll the TERec around to match up to the potentially updated scrollbar
  141.   values. This is really useful when the window resizes such that the
  142.   scrollbars become inactive and the TERec had been previously scrolled. }
  143.  
  144.       VAR
  145.         h : INTEGER;
  146.                 v : INTEGER;
  147.  
  148.       BEGIN
  149.               h := (theDoc^.theText^^.viewRect.left - theDoc^.theText^^.destRect.left) -
  150.                GetCtlValue(theDoc^.hScrollBar) + kTextOffset;
  151.                          
  152.                 v := (theDoc^.theText^^.viewRect.top -
  153.                theDoc^.theText^^.destRect.top) - GetCtlValue(theDoc^.vScrollBar) + kTextOffset;
  154.                                  
  155.         IF (h<>0) OR (v<>0) THEN
  156.                     BEGIN
  157.                         TEScroll(h, v, theDoc^.theText);
  158.                         DrawPageExtras(theDoc);
  159.                     END;
  160.       END;         { AdjustTE }
  161.  
  162.     {$S Main}
  163.  
  164.     PROCEDURE AdjustHV(isVert     : BOOLEAN;
  165.                        control    : ControlHandle;
  166.                            theDoc     : DPtr;
  167.                                              canRedraw: BOOLEAN);
  168.  
  169. {Calculate the new control maximum value and current value, whether it is the horizontal or
  170. vertical scrollbar. The vertical max is calculated by comparing the number of lines to the
  171. vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document
  172. width to the width of the viewRect. The current values are set by comparing the offset between
  173. the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by
  174. calling ShowControl.}
  175.  
  176. {TEStyleSample-vertical max originally used line by line calculations-lineheight was a
  177. constant value so it was easy to figure out what the range should be and pin the value
  178. within range. Now we need to use max and min values in pixels rather than in nlines}
  179.  
  180.       VAR
  181.         docTE          : TEHandle;
  182.         value            : INTEGER;
  183.                 max            : INTEGER;
  184.         oldValue    : INTEGER;
  185.                 oldMax        : INTEGER;
  186.                 sizeRect  : Rect;
  187.  
  188.       BEGIN        { AdjustHV }
  189.               sizeRect := theDoc^.pageSize;
  190.                 docTE    := theDoc^.theText;
  191.         oldValue := GetCtlValue(control);
  192.         oldMax   := GetCtlMax(control);
  193.         IF isVert THEN
  194.           BEGIN
  195.             { new for TEStyleSample }
  196.             max := (TEGetHeight(docTE^^.nLines, 0, docTE)) - (docTE^^.viewRect.bottom -
  197.                    docTE^^.viewRect.top);
  198.  
  199.           END
  200.         ELSE
  201.           max := sizeRect.right - (docTE^^.viewRect.right - docTE^^.viewRect.left);
  202.                 
  203.                 max := max + kTextOffset + kTextOffset; (* Allow over scroll by kTextOffset *)
  204.                 
  205.         IF max < 0 THEN
  206.           max := 0; { check for negative values }
  207.         SetCtlMax(control, max);
  208.         IF isVert THEN
  209.           value := docTE^^.viewRect.top - docTE^^.destRect.top
  210.         ELSE
  211.           value := docTE^^.viewRect.left - docTE^^.destRect.left;
  212.                     
  213.                 value := value + kTextOffset;
  214.                 
  215.         IF value < 0 THEN
  216.           value := 0
  217.         ELSE
  218.           IF value > max THEN
  219.             value := max; { pin the value to within range }
  220.                         
  221.         SetCtlValue(control, value);
  222.         IF canRedraw & ((max <> oldMax) | (value <> oldValue)) THEN
  223.           ShowControl(control); { check to see if the control can be re-drawn }
  224.       END;         { AdjustHV }
  225.  
  226.     {$S Main}
  227.  
  228.     PROCEDURE AdjustScrollValues(theDoc   : DPtr;
  229.                                  canRedraw: BOOLEAN);
  230.  
  231.     { Simply call the common adjust routine for the vertical and horizontal scrollbars. }
  232.  
  233.       BEGIN        { AdjustScrollValues }
  234.         AdjustHV(TRUE,  theDoc^.vScrollBar, theDoc, canRedraw);
  235.         AdjustHV(FALSE, theDoc^.hScrollBar, theDoc, canRedraw);
  236.       END;         { AdjustScrollValues }
  237.  
  238.     PROCEDURE GetTERect(window: WindowPtr;
  239.                         VAR teRect: Rect);
  240.  
  241. {   return a rectangle that is inset from the portRect by the size of
  242.   the scrollbars and a little extra margin. }
  243.  
  244.       BEGIN        { GetTERect }
  245.         teRect := window^.portRect;
  246.         teRect.bottom := teRect.bottom - kScrollbarAdjust; { and for the scrollbars }
  247.         teRect.right := teRect.right   - kScrollbarAdjust;
  248.       END;         { GetTERect }
  249.  
  250.     PROCEDURE AdjustScrollSizes(theDoc: DPtr);
  251.  
  252. { Re-calculate the position and size of the viewRect and the scrollbars.
  253.   kScrollTweek compensates for off-by-one requirements of the scrollbars
  254.   to have borders coincide with the growbox. }
  255.  
  256.       VAR
  257.         teRect        : Rect;
  258.  
  259.       BEGIN        { AdjustScrollSizes }
  260.         GetTERect(theDoc^.theWindow, teRect); {start with teRect}
  261.         WITH theDoc^.theWindow^.portRect DO
  262.           BEGIN                            
  263.             theDoc^.theText^^.viewRect := teRect;
  264.  
  265.             MoveControl(theDoc^.vScrollBar, right - kScrollbarAdjust, - 1);
  266.             SizeControl(theDoc^.vScrollBar, kScrollbarWidth, (bottom - top) - (kScrollbarAdjust -
  267.                         kScrollTweek));
  268.             MoveControl(theDoc^.hScrollBar, - 1, bottom - kScrollbarAdjust);
  269.             SizeControl(theDoc^.hScrollBar, (right - left) - (kScrollbarAdjust - kScrollTweek),
  270.                         kScrollbarWidth);
  271.           END;     { with }
  272.       END;         { AdjustScrollSizes }
  273.  
  274.     {$S Window}
  275.  
  276.     PROCEDURE AdjustScrollbars(theDoc: DPtr;
  277.                                needsResize: BOOLEAN);
  278.  
  279. { Turn off the controls by jamming a zero into their contrlVis fields
  280.   (HideControl erases them and we don't want that). If the controls are to
  281.   be resized as well, call the procedure to do that, then call the procedure
  282.   to adjust the maximum and current values. Finally reset the controls
  283.   to be visible if not in background. }
  284.  
  285.       BEGIN        { AdjustScrollbars }
  286.         WITH theDoc^ DO
  287.           BEGIN
  288.  
  289.             vScrollBar^^.contrlVis := kControlInvisible; { turn them off }
  290.             hScrollBar^^.contrlVis := kControlInvisible;
  291.  
  292.             IF needsResize THEN { move and size if needed }
  293.               AdjustScrollSizes(theDoc);
  294.  
  295.             AdjustScrollValues(theDoc, NOT needsResize); { fool with max and current value }
  296.  
  297.             { Now, restore visibility in case we never had to ShowControl during adjustment }
  298.  
  299.             IF NOT gInBackground THEN
  300.               BEGIN
  301.                 vScrollBar^^.contrlVis := kControlVisible; { turn them on }
  302.                 hScrollBar^^.contrlVis := kControlVisible;
  303.               END
  304.             ELSE
  305.               BEGIN (* make sure they stay invisible *)
  306.                 IF (vScrollBar^^.contrlVis <> 0) THEN
  307.                   HideControl(vScrollBar);
  308.                 IF (hScrollBar^^.contrlVis <> 0) THEN
  309.                   HideControl(hScrollBar);
  310.               END;
  311.           END;
  312.       END;         { AdjustScrollbars }
  313.  
  314.         {$S Window}
  315.         
  316.     PROCEDURE GetWinContentRect(theWindow:WindowPtr; VAR r:Rect);
  317.             BEGIN
  318.                 r        := theWindow^.portRect;
  319.                 r.right  := r.right  - kScrollBarAdjust;
  320.                 r.bottom := r.bottom - kScrollBarAdjust;
  321.             END; (* GetWinContentRect *)
  322.             
  323.         {$S Window}
  324.         
  325.         PROCEDURE InvalidateDocument(theDoc: DPtr);
  326.             VAR oldPort : GrafPtr;
  327.             
  328.             BEGIN
  329.         GetPort(oldPort);
  330.                 SetPort(theDoc^.theWindow);
  331.                 InvalRect(theDoc^.theWindow^.portRect);
  332.                 SetPort(oldPort);
  333.             END;
  334.                         
  335.     PROCEDURE ResizeWindow(theDoc: DPtr);
  336.  
  337.     { Called when the window has been resized to fix up the controls and content }
  338.  
  339.       BEGIN        { ResizeWindow }
  340.         AdjustScrollbars(theDoc, TRUE);
  341.         AdjustTE(theDoc);
  342.                 InvalidateDocument(theDoc);
  343.       END;         { ResizeWindow }
  344.  
  345.     PROCEDURE ResizePageSetupForDocument(theDoc: DPtr);
  346.  
  347.     { Called when the window has been resized to fix up the controls and content }
  348.  
  349.       BEGIN        { ResizePageSetupForDocument }
  350.                 theDoc^.pageSize := theDoc^.thePrintSetup^^.prInfo.rPage;
  351.                 OffsetRect(theDoc^.pageSize, -theDoc^.pageSize.left, -theDoc^.pageSize.top);
  352.             
  353.                 theDoc^.theText^^.destRect.right := theDoc^.theText^^.destRect.left + theDoc^.pageSize.right;
  354.                 
  355.                 TECalText(theDoc^.theText);
  356.                 
  357.                 ResizeWindow(theDoc);
  358.       END;         { ResizePageSetupForDocument }
  359.  
  360.     {$S Main}
  361.  
  362.     PROCEDURE CommonAction(control: ControlHandle;
  363.                            VAR amount: INTEGER);
  364.  
  365. { Common algorithm for setting the new value of a control. It returns the actual amount
  366.   the value of the control changed. Note the pinning is done for the sake of returning
  367.   the amount the control value changed. }
  368.  
  369.       VAR
  370.         value         : INTEGER;
  371.         max           : INTEGER;
  372.  
  373.       BEGIN        { CommonAction }
  374.         value := GetCtlValue(control); { get current value }
  375.         max := GetCtlMax(control); { and max value }
  376.         amount := value - amount;
  377.         IF amount < 0 THEN
  378.           amount := 0
  379.         ELSE
  380.           IF amount > max THEN
  381.             amount := max;
  382.         SetCtlValue(control, amount);
  383.         amount := value - amount; { calculate true change }
  384.       END;         { CommonAction }
  385.  
  386.     {$S Main}
  387.  
  388.     PROCEDURE VActionProc(control: ControlHandle;
  389.                           part: INTEGER);
  390.  
  391. { Determines how much to change the value of the vertical scrollbar by and how
  392.   much to scroll the TE record. }
  393.  
  394.       VAR
  395.         amount        : INTEGER;
  396.         window        : WindowPtr;
  397.         theDoc        : DPtr;
  398.  
  399.       BEGIN        { VActionProc }
  400.         IF part <> 0 THEN
  401.           BEGIN
  402.             window := control^^.contrlOwner;
  403.             theDoc := DPtrFromWindowPtr(window);
  404.             CASE part OF
  405.               inUpButton, inDownButton: amount := 24;
  406.               inPageUp, inPageDown:
  407.                 amount := theDoc^.theText^^.viewRect.bottom - theDoc^.theText^^.viewRect.top; { one
  408.                 page }
  409.             END;   { case }
  410.             IF (part = inDownButton) OR (part = inPageDown) THEN
  411.               amount := - amount; { reverse direction }
  412.             CommonAction(control, amount);
  413.             
  414.                         IF amount <> 0 THEN
  415.               BEGIN
  416.                                 TEScroll(0, amount, theDoc^.theText);
  417.                                 DrawPageExtras(theDoc);
  418.                             END;
  419.           END;     { if }
  420.       END;         { VActionProc }
  421.  
  422.     {$S Main}
  423.  
  424.     PROCEDURE HActionProc(control: ControlHandle;
  425.                           part: INTEGER);
  426.  
  427. { Determines how much to change the value of the horizontal scrollbar by and how
  428.   much to scroll the TE record. }
  429.  
  430.       VAR
  431.         amount        : INTEGER;
  432.         window        : WindowPtr;
  433.         theDoc        : DPtr;
  434.  
  435.       BEGIN        { HActionProc }
  436.         IF part <> 0 THEN
  437.           BEGIN
  438.             window := control^^.contrlOwner;
  439.             theDoc := DPtrFromWindowPtr(window);
  440.             CASE part OF
  441.               inUpButton, inDownButton: amount := kButtonScroll; { a few pixels }
  442.               inPageUp, inPageDown:
  443.                 amount := theDoc^.theText^^.viewRect.right - theDoc^.theText^^.viewRect.left; { a
  444.                 page }
  445.             END;   { case }
  446.             IF (part = inDownButton) OR (part = inPageDown) THEN
  447.               amount := - amount; { reverse direction }
  448.             CommonAction(control, amount);
  449.             IF amount <> 0 THEN
  450.               BEGIN
  451.                                 TEScroll(amount, 0, theDoc^.theText);
  452.                                 DrawPageExtras(theDoc);
  453.                             END;
  454.           END;     { if }
  455.       END;         { HActionProc }
  456.  
  457. {*-----------------------------------------------------------------------
  458.         Name:             ShowSelect
  459.         Purpose:        Scrolls the text selection into view.
  460.     -----------------------------------------------------------------------*}
  461.  
  462.     {$S Window}
  463.  
  464.     PROCEDURE ShowSelect(theDoc: DPtr);
  465.  
  466.       BEGIN
  467.         AdjustScrollbars(theDoc, FALSE);
  468.  
  469.                 (*
  470.                     Let TextEdit do the hard work of keeping the selection visible…
  471.                 *)
  472.  
  473.         TEAutoView(TRUE, theDoc^.theText);
  474.         TESelView(theDoc^.theText);
  475.         TEAutoView(FALSE, theDoc^.theText);
  476.  
  477.                 (*
  478.                     Now rematch the text and the scrollbars…
  479.                 *)
  480.  
  481.         SetCtlValue(theDoc^.hScrollBar,
  482.                     theDoc^.theText^^.viewRect.left - theDoc^.theText^^.destRect.left + kTextOffset);
  483.  
  484.         SetCtlValue(theDoc^.vScrollBar,
  485.                     theDoc^.theText^^.viewRect.top - theDoc^.theText^^.destRect.top  + kTextOffset);
  486.  
  487.       END; (* ShowSelect *)
  488.  
  489.     {$S Window}
  490.  
  491.     PROCEDURE OffsetWindow(aWindow: WindowPtr);
  492.  
  493.       VAR
  494.         theWidth, theHeight, theHScreen, theVScreen: INTEGER;
  495.         xWidth, xHeight, hMax, vMax, wLeft, wTop: INTEGER;
  496.  
  497.       BEGIN
  498.  
  499.         theWidth := aWindow^.portRect.right - aWindow^.portRect.left;
  500.         theHeight := aWindow^.portRect.bottom - aWindow^.portRect.top + kTBarHeight;
  501.  
  502.         theHScreen := screenBits.bounds.right - screenBits.bounds.left;
  503.         theVScreen := screenBits.bounds.bottom - screenBits.bounds.top;
  504.  
  505.         xWidth := theHScreen - theWidth;
  506.         xHeight := theVScreen - (theHeight + kMBarHeight);
  507.  
  508.         hMax := (xWidth DIV kVOffset) + 1;
  509.         vMax := (xHeight DIV KVOffset) + 1;
  510.  
  511.         gWCount := gWCount + 1;
  512.  
  513.         wLeft := (gWCount MOD hMax) * kVOffset;
  514.         wTop := ((gWCount MOD vMax) * KVOffset) + kTBarHeight + kMBarHeight;
  515.  
  516.         MoveWindow(aWindow, wLeft, wTop, FALSE);
  517.       END;
  518.  
  519.     PROCEDURE GetLocalUpdateRgn(window: WindowPtr;
  520.                                 localRgn: RgnHandle);
  521.  
  522.     { Returns the update region in local coordinates }
  523.  
  524.       BEGIN        { GetLocalUpdateRgn }
  525.         CopyRgn(WindowPeek(window)^.updateRgn, localRgn); { save old update region }
  526.         WITH window^.portBits.bounds DO
  527.           OffsetRgn(localRgn, left, top); { convert to local coords }
  528.       END;         { GetLocalUpdateRgn }
  529.  
  530.     {$S Window}
  531.  
  532.     PROCEDURE MyGrowWindow(w: WindowPtr;
  533.                            p: Point);
  534.  
  535.       VAR
  536.         savePort      : GrafPtr;
  537.         theResult     : Longint;
  538.         r             : Rect;
  539.  
  540.       BEGIN
  541.         GetPort(savePort);
  542.         SetPort(w);
  543.         SetRect(r, 80, 80, screenBits.bounds.right, screenBits.bounds.bottom);
  544.         theResult := GrowWindow(w, p, r);
  545.         IF (theResult <> 0) THEN
  546.           IssueSizeWindow(w, LoWord(theResult), HiWord(theResult));
  547.  
  548.         SetPort(savePort);
  549.       END;
  550.  
  551.     {$S Window}
  552.  
  553.     PROCEDURE DoZoom(w: WindowPtr;
  554.                      c: INTEGER;
  555.                      p: Point);
  556.  
  557.       VAR
  558.         savePort      : GrafPtr;
  559.  
  560.       BEGIN
  561.         GetPort(savePort);
  562.         SetPort(w);
  563.         IF TrackBox(w, p, c) THEN
  564.           BEGIN
  565.             EraseRect(w^.portRect);
  566.             IssueZoomCommand(w, c);
  567.           END;
  568.       END;
  569.  
  570.     {$S Window}
  571.  
  572.     PROCEDURE DoContent(theWindow: WindowPtr;
  573.                         theEvent: EventRecord);
  574.  
  575.       VAR
  576.         cntlCode      : INTEGER;
  577.         part          : INTEGER;
  578.         theControl    : ControlHandle;
  579.         savePort      : GrafPtr;
  580.         extend        : BOOLEAN;
  581.         theDoc        : DPtr;
  582.         value         : INTEGER;
  583.  
  584.       BEGIN
  585.         GetPort(savePort);
  586.         SetPort(theWindow);
  587.         theDoc := DPtrFromWindowPtr(theWindow);
  588.  
  589.         GlobalToLocal(theEvent.where);
  590.         cntlCode := FindControl(theEvent.where, theWindow, theControl);
  591.         IF (cntlCode = 0) THEN
  592.           BEGIN
  593.             {only extend the selection if the shiftkey is down}
  594.             extend := (BitAnd(theEvent.modifiers, ShiftKey) <> 0);
  595.  
  596.             IF ptInRect(theEvent.where, theDoc^.theText^^.viewRect) THEN
  597.               TEClick(theEvent.where, extend, theDoc^.theText);
  598.           END
  599.         ELSE
  600.           IF cntlCode = inThumb THEN
  601.             BEGIN
  602.               value := GetCtlValue(theControl);
  603.                             part := TrackControl(theControl, theEvent.where, NIL);
  604.               IF (part <> 0) THEN
  605.                 BEGIN
  606.                   value := value - GetCtlValue(theControl);
  607.                   IF value <> 0 THEN
  608.                                         BEGIN
  609.                                             IF theControl = theDoc^.vScrollBar THEN
  610.                                                 TEScroll(0, value, theDoc^.theText)
  611.                                             ELSE
  612.                                                 TEScroll(value, 0, theDoc^.theText);
  613.                                             DrawPageExtras(theDoc);
  614.                                         END;
  615.                 END; { if }
  616.             END
  617.           ELSE
  618.             IF theControl = theDoc^.vScrollBar THEN
  619.               part := TrackControl(theControl, theEvent.where, @VActionProc)
  620.             ELSE
  621.               part := TrackControl(theControl, theEvent.where, @HActionProc);
  622.  
  623.         SetPort(savePort);
  624.  
  625.       END;
  626.             
  627.         (*$S Window*)
  628.         PROCEDURE DoActivate(theWindow: WindowPtr;
  629.                                                  activate : BOOLEAN);
  630.     
  631.             VAR
  632.                 err                     : OSErr;
  633.                 r                         : Rect;
  634.                 theDoc                : DPtr;
  635.     
  636.             BEGIN
  637.                 IF (theWindow <> NIL) THEN
  638.                     BEGIN
  639.                         theDoc := DPtrFromWindowPtr(theWindow);
  640.                         SetPort(theWindow);
  641.                         DrawGrowIcon(theWindow);
  642.                         GetWinContentRect(theWindow, r);
  643.                         InvalRect(r);
  644.                         IF activate THEN
  645.                             BEGIN
  646.                                 TEActivate(theDoc^.theText);
  647.                                 ShowControl(theDoc^.vscrollBar);
  648.                                 ShowControl(theDoc^.hscrollBar);
  649.                                 DisableItem(myMenus[editM], undoCommand);
  650.                                 err := TEFromScrap;
  651.                                 IF (gWCount = 0) THEN
  652.                                     SetShortMenus;
  653.                             END
  654.                         ELSE
  655.                             BEGIN
  656.                                 TEDeactivate(theDoc^.theText);
  657.                                 HideControl(theDoc^.vscrollBar);
  658.                                 HideControl(theDoc^.hscrollBar);
  659.                                 err := ZeroScrap;
  660.                                 err := TEToScrap;
  661.                             END;
  662.                     END;
  663.             END;
  664.     
  665.     {$S Window}        
  666.         PROCEDURE GetPageEnds(pageHeight: INTEGER;
  667.                                                     theText        : TEHandle;
  668.                               pageBounds: PPageEnds;
  669.                                                     VAR nPages: INTEGER);
  670.                                                         
  671.             VAR pageBase            : INTEGER; (* total pixel offset of pages so far *)
  672.                     thisLine            : INTEGER;
  673.                     lastLine            : INTEGER; 
  674.                     thisPage            : INTEGER; (* Current page being calced *)
  675.                     pageSoFar           : INTEGER; (* Page height used so far by lines on this page *)
  676.                     thisLineH       : INTEGER; (* Height of text line *)
  677.                     pageFirstLine : INTEGER; (* Line # of top of page *)
  678.                     
  679.             BEGIN
  680.               pageBase   := 0;
  681.                 thisLine   := 1;
  682.                 lastLine   := theText^^.nLines;
  683.                 
  684.                 thisPage   := 1;
  685.                 pageSoFar  := 0;
  686.                 WHILE (thisLine <= lastLine) OR (pageSoFar<>0) DO
  687.                     BEGIN
  688.                       pageFirstLine := thisLine;
  689.                         thisLineH     := TEGetHeight(thisLine, thisLine, theText);
  690.                         
  691.                         WHILE (thisLineH+pageSoFar< pageHeight) AND
  692.                               (thisLine <= lastLine) DO
  693.                             BEGIN
  694.                                 pageSoFar := pageSoFar + thisLineH;
  695.                                 thisLine  := thisLine +1;
  696.                             thisLineH := TEGetHeight(thisLine, thisLine, theText);
  697.                             END;
  698.                             
  699.                         IF (pageSoFar<>0) THEN
  700.                             BEGIN
  701.                                 pageBounds^[thisPage] := pageSoFar+pageBase;
  702.                                 pageBase := pageBounds^[thisPage];
  703.                                 thisPage := thisPage + 1;
  704.                           pageSoFar:= 0;
  705.                           END;
  706.                             
  707.                         (*
  708.                             Special case text line taller than page
  709.                         *)
  710.                         
  711.                         IF (thisLine  = pageFirstLine) AND
  712.                            (thisLineH > pageHeight) THEN
  713.                             BEGIN
  714.                               REPEAT
  715.                                   pageBounds^[thisPage] := pageBase+pageHeight;
  716.                                     pageBase   := pageBounds^[thisPage];
  717.                                     thisPage   := thisPage + 1;
  718.                                     thisLineH  := thisLineH - pageHeight;
  719.                                 UNTIL (thisLineH < pageHeight);
  720.                                 pageSoFar := thisLineH; (* Carry bottom of large line to next page *)
  721.                                 thisLine  := thisLine + 1; (* carry xs on as pageSoFar and start measuring next line *)
  722.                             END;
  723.                     END;
  724.                     
  725.                 nPages := thisPage -1;
  726.                 
  727.             END; (* GetPageEnds *)
  728.         
  729.         PROCEDURE DrawPageBreaks(theDoc : DPtr);
  730.             VAR PageEnds   : PageEndsArray;
  731.                 nPages     : INTEGER;
  732.                     ctr        : INTEGER;
  733.                     lineBase   : INTEGER;
  734.                     viewRect   : Rect;
  735.                     pageHeight : INTEGER;
  736.                     
  737.             BEGIN
  738.                 pageHeight := theDoc^.pageSize.bottom - theDoc^.pageSize.top;
  739.                 
  740.                 GetPageEnds(pageHeight,
  741.                                         theDoc^.theText,
  742.                                         @pageEnds,
  743.                                         nPages);
  744.                                             
  745.                 lineBase := theDoc^.theText^^.destRect.top;
  746.                 viewRect := theDoc^.theText^^.viewRect;
  747.  
  748.                 PenPat(gray);
  749.                 FOR ctr := 1 to nPages-1 DO
  750.                     BEGIN
  751.                         MoveTo(viewRect.left, lineBase+PageEnds[ctr]);
  752.                         LineTo(viewRect.right,lineBase+PageEnds[ctr]);
  753.                     END;
  754.                 PenNormal;
  755.             END; (*    DrawPageBreaks *)
  756.             
  757.         PROCEDURE DrawPageExtras(theDoc:DPtr);
  758.             VAR oldPort    : GrafPtr;
  759.                     oldClip         : RgnHandle;
  760.                 rectToClip : Rect;
  761.             
  762.             BEGIN
  763.               GetPort(oldPort);
  764.                 SetPort(theDoc^.theWindow);
  765.                 
  766.             oldClip := NewRgn;
  767.                 GetClip(oldClip);
  768.                 
  769.                 GetWinContentRect(theDoc^.theWindow,rectToClip);
  770.                 ClipRect(rectToClip);
  771.                 
  772.               { draw the borders }
  773.  
  774.         IF theDoc^.showBorders THEN
  775.           ShowSectionBorders(theDoc);
  776.                     
  777.                 { and then the page breaks }
  778.                 
  779.                 DrawPageBreaks(theDoc);
  780.                 
  781.                 SetClip(oldClip);
  782.                 
  783.                 DisposeRgn(oldClip);
  784.                 
  785.                 SetPort(oldPort);
  786.             END; (* DrawPageExtras *)
  787.  
  788.     PROCEDURE DoUpdate(theDoc: DPtr);
  789.  
  790.       VAR
  791.         aWindow       : WindowPtr;
  792.         savePort      : GrafPtr;
  793.         rectClip      : Rect;
  794.  
  795.       BEGIN
  796.         aWindow := theDoc^.theWindow;
  797.         GetPort(savePort);
  798.         SetPort(aWindow);
  799.         BeginUpdate(aWindow);
  800.  
  801.         ClipRect(aWindow^.portRect);
  802.         EraseRect(aWindow^.portRect);
  803.         DrawControls(aWindow);
  804.         DrawGrowIcon(aWindow);
  805.  
  806.                 GetWinContentRect(aWindow, rectClip);
  807.         ClipRect(rectClip);
  808.  
  809.         TEUpdate(aWindow^.portRect, theDoc^.theText);
  810.  
  811.                 DrawPageExtras(theDoc);
  812.                 
  813.         EndUpdate(aWindow);
  814.         ClipRect(aWindow^.portRect);
  815.  
  816.         SetPort(savePort);
  817.       END; (* DoUpdate *)
  818.  
  819.     {$S Window}
  820.  
  821.     FUNCTION NewDocument(isForOldDoc:Boolean): DPtr;
  822.       VAR
  823.         destRect      : Rect;
  824.         viewRect      : Rect;
  825.         vScrollRect   : Rect;
  826.         hScrollRect   : Rect;
  827.         myDoc         : DPtr;
  828.         myWindow      : WindowPtr;
  829.         vScroll       : ControlHandle;
  830.         hScroll       : ControlHandle;
  831.                 theName       : Str255;
  832.                 newNumber     : Str255;
  833.  
  834.       BEGIN
  835.         IF (gWCount = 0) THEN
  836.           SetLongMenus;
  837.  
  838.         myDoc := NIL;
  839.         myWindow := GetNewWindow(windowID, NIL, Pointer( - 1));
  840.         IF (myWindow <> NIL) THEN
  841.           BEGIN
  842.                         IF (NOT isForOldDoc) THEN
  843.                             BEGIN
  844.                                 GetWTitle(myWindow, theName);
  845.                                 gNewDocCount := gNewDocCount+1;
  846.                                 NumToString(gNewDocCount, newNumber);
  847.                                 IF (gNewDocCount>1) THEN
  848.                                     BEGIN
  849.                                         theName := CONCAT(theName,' #');
  850.                                         theName := CONCAT(theName, newNumber);
  851.                                         SetWTitle(myWindow, theName);
  852.                                     END;
  853.                             END;
  854.                     
  855.             OffsetWindow(myWindow);
  856.  
  857.             SetPort(myWindow);
  858.  
  859.             myDoc := DPtr(NewPtr(sizeOf(DocRec)));
  860.  
  861.             SetWRefCon(myWindow, ord4(myDoc));
  862.  
  863.             myDoc^.theWindow := myWindow;
  864.  
  865.             vScrollRect := myWindow^.portRect;
  866.  
  867.             vScrollRect.left  := vScrollRect.right - kScrollBarAdjust;
  868.             vScrollRect.right := vScrollRect.left + kScrollBarWidth;
  869.  
  870.             vScrollRect.bottom := vScrollRect.bottom - 14;
  871.             vScrollRect.top    := vScrollRect.top - 1;
  872.                         
  873.             vScroll := NewControl(myWindow, vScrollRect, '', TRUE, 0, 0, 0, scrollBarProc, 0);
  874.  
  875.             hScrollRect := myWindow^.portRect;
  876.             hScrollRect.top := hScrollRect.bottom - kScrollBarAdjust;
  877.             hScrollRect.bottom := hScrollRect.top + kScrollBarWidth;
  878.  
  879.             hScrollRect.right := hScrollRect.right - 14;
  880.             hScrollRect.left := hScrollRect.left - 1;
  881.             hScroll := NewControl(myWindow, hScrollRect, '', TRUE, 0, 0, 0, scrollBarProc, 0);
  882.  
  883.             myDoc^.vScrollBar := vScroll;
  884.             myDoc^.hScrollBar := hScroll;
  885.             myDoc^.lastID := 0;
  886.             
  887.                         myDoc^.firstSection := NIL;
  888.             myDoc^.lastSection  := NIL;
  889.             myDoc^.numSections  := 0;
  890.                         
  891.             myDoc^.dirty := FALSE;
  892.  
  893.             GetTERect(myWindow, viewRect);
  894.             destRect := viewRect;
  895.  
  896.             myDoc^.theFont := Times;
  897.             myDoc^.theStyle := [];
  898.             myDoc^.theSize := 12;
  899.  
  900.                         myDoc^.thePrintSetup := THPrint(NewHandle(SizeOf(TPrint)));
  901.                         
  902.                         PrOpen;
  903.                         PrintDefault(myDoc^.thePrintSetup);
  904.                         PrClose;
  905.                         
  906.                         myDoc^.pageSize := myDoc^.thePrintSetup^^.prInfo.rPage;
  907.                         OffsetRect(myDoc^.pageSize, -myDoc^.pageSize.left, -myDoc^.pageSize.top);
  908.                         
  909.             destRect.right := destRect.left + myDoc^.pageSize.right;
  910.                         
  911.                         OffsetRect(destRect, kTextOffset, kTextOffset);
  912.                         
  913.             TextFont(Times);
  914.             TextSize(12);
  915.             TextFace([]);
  916.  
  917.             myDoc^.theText := TEStylNew(destRect, viewRect);
  918.  
  919.       {
  920.       SetClikLoop(@AutoScroll, myDoc^.theText);
  921.       }
  922.  
  923.             myDoc^.theFileName := '';
  924.                         myDoc^.everSaved   := FALSE;
  925.             myDoc^.theWindow   := myWindow;
  926.                         
  927.                         myDoc^.showBorders := FALSE;
  928.  
  929.             ResizeWindow(myDoc);
  930.           END;
  931.         NewDocument := myDoc;
  932.       END;
  933.  
  934.     {$S Window}
  935.  
  936.     PROCEDURE CloseMyWindow(aWindow: WindowPtr);
  937.  
  938.       VAR
  939.         aDocument     : DPtr;
  940.         theText       : TEHandle;
  941.  
  942.       BEGIN
  943.         HideWindow(aWindow);
  944.         aDocument := DPtrFromWindowPtr(aWindow);
  945.                 
  946.         theText   := aDocument^.theText;
  947.         TEDispose(theText);
  948.                 
  949.                 IF (aDocument^.thePrintSetup<>NIL) THEN
  950.                     DisposHandle(Handle(aDocument^.thePrintSetup));
  951.                     
  952.         DisposPtr(Ptr(aDocument));
  953.         DisposeWindow(aWindow);
  954.  
  955.         gWCount := gWCount - 1;
  956.  
  957.         {if there are no more windows open, set up the short menus}
  958.         IF gWCount = 0 THEN
  959.           SetShortMenus;
  960.                     
  961.       END;
  962.             
  963.     (*
  964.         Name     : PrintWindow
  965.         Function : Prints the document supplied in theDoc. askUser controls interaction
  966.                    with the user.
  967.                              
  968.                              Uses extra memory equal to the size of the textedit use in the 
  969.                              printed document.
  970.     *)
  971.     
  972.     PROCEDURE PrintWindow(theDoc:DPtr; askUser:BOOLEAN);
  973.         VAR oldPort                 : GrafPtr;
  974.                 printerTE                    : TEHandle;
  975.                 printerPort             : TPPrPort;
  976.                 printView                    : Rect;
  977.                 printerTextStyles : StScrpHandle;
  978.                 pageBounds                : PageEndsArray;
  979.                 nPages                        : INTEGER;
  980.                 oldSelStart                : INTEGER;
  981.                 oldSelEnd                    : INTEGER;
  982.                 pageCtr                        : INTEGER;
  983.                 abort                            : BOOLEAN;
  984.                 rectToClip        : Rect;
  985.                 thePrinterStatus    :    TPrStatus;
  986.                 progressDialog    : DialogPtr;
  987.                 
  988.         BEGIN
  989.             abort := FALSE;
  990.             
  991.             (*
  992.                 Preserve the current port
  993.             *)
  994.             GetPort(oldPort);
  995.             PrOpen;
  996.             
  997.             
  998.             IF askUser THEN
  999.                 abort := NOT PrJobDialog(theDoc^.thePrintSetup);
  1000.                 
  1001.             IF abort THEN
  1002.                 BEGIN
  1003.                     PrClose;
  1004.                     Exit(PrintWindow);
  1005.                 END;
  1006.             
  1007.             progressDialog := GetNewDialog(1005, NIL, POINTER(-1));
  1008.             
  1009.             DrawDialog(progressDialog);
  1010.             
  1011.             printerPort := PrOpenDoc(theDoc^.thePrintSetup, NIL, NIL);
  1012.             SetPort(GrafPtr(printerPort));
  1013.             
  1014.             (*
  1015.                 Put the window text into the printer port
  1016.             *)
  1017.             
  1018.             printView := theDoc^.thePrintSetup^^.prInfo.rPage;
  1019.             printerTE := TEStylNew(printView, printView);
  1020.  
  1021.             oldSelStart := theDoc^.theText^^.selStart;
  1022.             oldSelEnd   := theDoc^.theText^^.selEnd;
  1023.             
  1024.             TESetSelect(0,theDoc^.theText^^.teLength, theDoc^.theText);
  1025.  
  1026.             printerTextStyles := GetStylScrap(theDoc^.theText);
  1027.  
  1028.             TESetSelect(oldSelStart, oldSelEnd, theDoc^.theText);
  1029.             
  1030.             HLock(Handle(theDoc^.theText^^.hText));
  1031.             
  1032.             TEStylInsert(    Ptr(theDoc^.theText^^.hText^),
  1033.                                         theDoc^.theText^^.teLength,
  1034.                                         printerTextStyles,
  1035.                                         printerTE);
  1036.                                                 
  1037.             HUnLock(Handle(theDoc^.theText^^.hText));
  1038.  
  1039.             (*
  1040.                 Work out the offsets
  1041.             *)
  1042.             printerTE^^.destRect := printView; (* GetPageEnds calls TECalText *)
  1043.             
  1044.             GetPageEnds(printView.bottom-printView.top,
  1045.                                     printerTE,
  1046.                       @pageBounds,
  1047.                                     nPages);
  1048.             
  1049.             TEDeactivate(printerTE);
  1050.  
  1051.             FOR pageCtr := 1 to nPages DO
  1052.                 IF NOT abort THEN
  1053.                     BEGIN
  1054.                         PrOpenPage(printerPort, NIL);
  1055.                                                     
  1056.                         rectToClip := printView;
  1057.                         
  1058.                         IF (pageCtr > 1) THEN
  1059.                             rectToClip.bottom := rectToClip.top + (pageBounds[pageCtr]-pageBounds[pageCtr-1])
  1060.                         ELSE
  1061.                             rectToClip.bottom := rectToClip.top + pageBounds[pageCtr];
  1062.                             
  1063.                         ClipRect(rectToClip);
  1064.                         
  1065.                         IF (PrError = iPrAbort) THEN
  1066.                             abort := TRUE;
  1067.                             
  1068.                         IF not abort THEN
  1069.                             TEUpdate(printView, printerTE);
  1070.                                                 
  1071.                         IF (PrError = iPrAbort) THEN
  1072.                             abort := TRUE;
  1073.                             
  1074.                         PrClosePage(printerPort);
  1075.                         
  1076.                         TEScroll(0,rectToClip.top-rectToClip.bottom, printerTE);
  1077.                     END;
  1078.  
  1079.             TEDispose(printerTE);
  1080.                         
  1081.             PrCloseDoc(printerPort);
  1082.             
  1083.             IF ( theDoc^.thePrintSetup^^.prJob.bJDocLoop = bSpoolLoop ) AND 
  1084.                ( PrError = noErr )  AND
  1085.                  (NOT abort) THEN
  1086.                 PrPicFile( theDoc^.thePrintSetup, NIL, NIL, NIL, thePrinterStatus);
  1087.  
  1088.             PrClose;
  1089.             
  1090.             DisposDialog(progressDialog);
  1091.             
  1092.             SetPort(oldPort);
  1093.             InvalRect(oldPort^.portRect);
  1094.         END;
  1095. END.
  1096.